package com.ccp.dev.core.basic.mybatis.dialect;


import com.ccp.dev.core.basic.mybatis.Dialect;

/**
 * oracle 方言处理。
 *
 * @author badqiu
 */
public class OracleDialect extends Dialect {
    @Override
    public boolean supportsLimit() {
        return true;
    }

    @Override
    public boolean supportsLimitOffset() {
        return true;
    }

    @Override
    public String getLimitString(String sql, int offset, String offsetPlaceholder, int limit, String limitPlaceholder) {
        sql = sql.trim();
        boolean isForUpdate = false;
        if (sql.toLowerCase().endsWith(" for update")) {
            sql = sql.substring(0, sql.length() - 11);
            isForUpdate = true;
        }
        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
        if (offset > 0) {
            pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
        } else {
            pagingSelect.append("select * from ( ");
        }
        pagingSelect.append(sql);
        if (offset > 0) {
            String endString = offsetPlaceholder + "+" + limitPlaceholder;
            pagingSelect.append(" ) row_ ) where rownum_ <= " + endString + " and rownum_ > " + offsetPlaceholder);
        } else {
            pagingSelect.append(" ) where rownum <= " + limitPlaceholder);
        }
        if (isForUpdate) {
            pagingSelect.append(" for update");
        }
        return pagingSelect.toString();
    }

    @Override
    public String getLimitString(String sql, int offset, int limit) {
        sql = sql.trim();
        boolean isForUpdate = false;
        if (sql.toLowerCase().endsWith(" for update")) {
            sql = sql.substring(0, sql.length() - 11);
            isForUpdate = true;
        }
        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
        if (offset > 0) {
            pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
        } else {
            pagingSelect.append("select * from ( ");
        }
        pagingSelect.append(sql);
        if (offset > 0) {
            //开始
            pagingSelect.append(" ) row_ ) where rownum_ <= " + limit + " and rownum_ > " + offset);
        } else {
            pagingSelect.append(" ) where rownum <= " + limit);
        }
        if (isForUpdate) {
            pagingSelect.append(" for update");
        }
        return pagingSelect.toString();
    }

    /**
     *
     * 功能描述: 处理分页备份方法，该方法可以提高单表分页时的执行效率，备份方法，没实际使用
     *
     * @param: [sql, offset, limit]
     * @return: java.lang.String
     * @auther: dfz
     * @date: 2019/5/14 18:40
     */
    public String getLimitStringBak(String sql, int offset, int limit) {

        sql = sql.trim().toLowerCase();
        boolean isForUpdate = false;
        if (sql.toLowerCase().endsWith(" for update")) {
            sql = sql.substring(0, sql.length() - 11);
            isForUpdate = true;
        }
        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
        String orderSql="";
        //是否存在排序关键字order
        Boolean containsOrder=sql.contains("order");

        if(containsOrder){
            //order by sql片段
            orderSql = "  "+sql.substring(sql.indexOf("order"));
            sql =sql.substring(0, sql.indexOf("order"));
        }
        /**
         * 判断sql中是否有where条件，
         * 如果有条件 就在条件中追加 分页的rownum
         * 如果没有条件  就直接追加where
         * order by 最后再追加
         */
        pagingSelect.append("select * from ( select rownum rownum_, ");
        //从select关键字开始截取sql 只要后面的sql串
        pagingSelect.append(sql.substring(sql.indexOf("select")+6));
        if (sql.contains("where")) {
            //有条件查询，在原来的where中追加分页的rownum的条件
            pagingSelect.append("   and  rownum<="+limit+orderSql+" ) ");
        } else {
            //没有条件 新生成一个where rownum<=？
            //先查出最大的sql条数
            pagingSelect.append(" where rownum<="+limit+ orderSql+"  ) ");
        }
        if(offset>0){
            pagingSelect.append(" where rownum_> "+offset);
        }

        if (isForUpdate) {
            pagingSelect.append(" for update");
        }
        return pagingSelect.toString();
    }
}
